package com.k8.exchange;

import com.k8.rpc.RpcException;
import com.k8.rpc.invoke.Invoker;
import com.k8.rpc.invoke.invocation.RpcInvocation;
import com.k8.rpc.invoke.invocation.RpcInvocationTemplate;
import com.k8.rpc.result.Result;
import com.k8.rpc.result.RpcResult;
import com.k8.rpc.serialize.Serializer;
import com.k8.rpc.url.URL;
import com.key.w8.common.execute.ChainExecuteHandler;
import com.key.w8.http1.connection.Connection;
import com.key.w8.http1.connection.environment.Http1Environment;
import com.key.w8.http1.endpoint.HServer;
import com.key.w8.http1.endpoint.ServerConnectionBuilder;
import com.key.w8.http1.entity.HttpRequest;
import com.key.w8.http1.handler.codec.CodecBuilder;
import com.key.w8.http1.handler.codec.DefaultCodecBuilder;
import io.netty.buffer.ByteBuf;
import io.netty.util.ReferenceCountUtil;
import lombok.Data;
import lombok.experimental.Accessors;

/**
 * @Author: k8
 * @CreateTime: 2025-08-15
 * @Version: 1.0
 */
@Data
@Accessors(chain = true)
public class ServerBuilder {
    private URL protocolUrl;
    private Serializer serializer;
    private SerializeServerResolver responseResolver;

    public HServer build() {
        Http1Environment environment = EnvironmentUtil.urlConvert2ServerEnvironment(protocolUrl);
        ServerConnectionBuilder serverConnectionBuilder = new ServerConnectionBuilder();
        serverConnectionBuilder.addExecuteHandler(new ChainExecuteHandler() {
            @Override
            public Object onInvoke(Object msg, Object attach) {
                if (!(msg instanceof HttpRequest)) throw new IllegalArgumentException();
                RpcInvocation invocation = null;
                Result<?> result = new RpcResult<>();
                try {
                    HttpRequest request = (HttpRequest) msg;
                    invocation = (RpcInvocation) request.complexObject();
                    RpcInvocationTemplate template = (RpcInvocationTemplate) invocation.getTemplate();
                    if (template == null) {
                        result.setException(new RpcException("There is no corresponding service implementation for this invocation key."));
                    } else {
                        Invoker<?> invoker = template.getInvoker();
                        result = invoker.invoke(invocation);
                    }
                } catch (Throwable throwable) {
                    result.setException(throwable);
                }
                return result;
            }
        });
        CodecBuilder codecBuilder = new DefaultCodecBuilder();
        codecBuilder.addHttpObjectServerResolver(responseResolver);
        return new HServer(environment, serverConnectionBuilder, codecBuilder);
    }
}
